package com.cj.stock.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cj.common.constant.Constant;
import com.cj.common.exception.BaseException;
import com.cj.stock.dao.StockMapper;
import com.cj.stock.entity.Stock;
import com.cj.stock.service.StockService;
import lombok.extern.slf4j.Slf4j;
import org.dromara.hmily.annotation.HmilyTCC;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Map;
import java.util.Objects;

/**
 * @Author cheng jun
 * @Description:
 * @Date 2021/7/25 17:51
 */
@Service
@Slf4j
public class StockServiceImpl extends ServiceImpl<StockMapper, Stock> implements StockService {

    @Override
    @HmilyTCC(confirmMethod="commit", cancelMethod="rollback")
    public boolean deleteStock(Map<String, Object> map) {
        log.info("stock try begin 开始执行...");
        // 更新库存
        String commodityId = String.valueOf(map.get("commodityId"));
        long commodityNum = Long.parseLong(String.valueOf(map.get("commodityNum")));
        if(updateStock(commodityId, Constant.HMILY_TRY, commodityNum)){
            // 更新库存失败
            throw new BaseException("bank1 try 更新订单失败");
        }

        log.info("stock try end 结束执行...xid:{}");

        return true;
    }

    /**
     * confirm方法
     * 	confirm幂等校验
     * 	正式增加金额
     * @param map
     */
    @Transactional(rollbackFor = BaseException.class)
    public boolean commit(Map<String, Object> map){
        log.info("stock confirm begin 开始执行...");

        // 更新库存
        String commodityId = String.valueOf(map.get("commodityId"));
        long commodityNum = Long.parseLong(String.valueOf(map.get("commodityNum")));
        boolean flag = updateStock(commodityId, Constant.HMILY_CONFIRM, commodityNum);

        log.info("stock confirm end 结束执行...");

        return flag;
    }


    /**
     * 回滚
     * @param map
     * @return
     */
    public boolean rollback(Map<String, Object> map){
        log.info("stock cancel begin 开始执行...");

        // 更新库存
        String commodityId = String.valueOf(map.get("commodityId"));
        long commodityNum = Long.parseLong(String.valueOf(map.get("commodityNum")));
        boolean flag = updateStock(commodityId, Constant.HMILY_CANCEL, commodityNum);

        log.info("stock cancel end 结束执行...");

        return flag;
    }

    /**
     * 更新库存
     * @param commodityId
     * @param type
     * @param commodityNum
     * @return
     */
    public boolean updateStock(String commodityId, String type, long commodityNum) {
        QueryWrapper<Stock> queryWrapper = new QueryWrapper();
        Stock stock = new Stock();

        // 判断是try还是cancel还是confirm
        if (Objects.equals(Constant.HMILY_TRY, type)) {
            // 查看库存是否够
            long nums = getNum(commodityId);
            if ((nums - commodityNum) < 1) {
                throw new BaseException("库存不够");
            }

            stock.setCommodityId(commodityId);
            queryWrapper.eq("lock_num", commodityNum);
        } else if (Objects.equals(Constant.HMILY_CONFIRM, type)) {
            // 查询库存
            long nums = getNum(commodityId);

            stock.setCommodityId(commodityId);
            queryWrapper.eq("num", nums - commodityNum);
            queryWrapper.eq("lock_num", Constant.LOCK_NUM);
        } else {
            stock.setCommodityId(commodityId);
            queryWrapper.eq("lock_num", Constant.LOCK_NUM);
        }

        return this.update(stock, queryWrapper);
    }

    /**
     * 查看库存
     * @param commodityId
     * @return
     */
    public long getNum(String commodityId) {
        QueryWrapper<Stock> queryWrapper = new QueryWrapper();
        queryWrapper.eq("commodity_id", commodityId);
        queryWrapper.select("num");
        Stock stock = this.getOne(queryWrapper);

        return null != stock ? stock.getNum() : 0L;
    }
}
